# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

# -*- coding: utf-8 -*-
"""
测试类型转换操作符的代码生成

验证 bool(), int(), str() 等类型转换函数能够正确调用对象的转换方法
而不是简单的构造函数调用。

例如：
- bool(empty_list) 应该生成 !empty_list.empty()
- int(float_value) 应该生成 static_cast<int>(float_value)
- str(int_value) 应该生成 std::to_string(int_value)
"""

from tests.pytests.helpers.codegen_helpers import compile_chunk, assert_code_contains


def test_bool_conversion_list():
    """测试 bool(list) 使用 __bool__ 重载方法"""

    def test_bool_conversion() -> None:
        empty_list: list[int] = []
        if bool(empty_list):
            pass

    cpp = compile_chunk(test_bool_conversion)
    assert_code_contains(
        cpp,
        """
        void test_bool_conversion() {
            mc::array<int> empty_list = {};
            if (!empty_list.empty()) {
            }
        }
        """,
    )


def test_bool_conversion_dict():
    """测试 bool(dict) 使用 __bool__ 重载方法"""

    def test_bool_dict() -> None:
        empty_dict: dict[str, int] = {}
        if bool(empty_dict):
            pass

    cpp = compile_chunk(test_bool_dict)
    assert_code_contains(
        cpp,
        """
        void test_bool_dict() {
            mc::dict empty_dict = mc::dict{};
            if (!empty_dict.empty()) {
            }
        }
        """,
    )


def test_bool_conversion_set():
    """测试 bool(set) 使用 set.__bool__ 重载方法"""

    def test_bool_set() -> None:
        empty_set: set[int] = set()
        if bool(empty_set):
            pass

    cpp = compile_chunk(test_bool_set)
    assert_code_contains(
        cpp,
        """
        void test_bool_set() {
            mcpy::variant_set empty_set = mcpy::variant_set{};
            if (!empty_set.empty()) {
            }
        }
        """,
    )


def test_bool_conversion_in_expression():
    """测试 bool() 在表达式中使用"""

    def test_bool_expr() -> None:
        items: list[int] = []
        result: bool = bool(items) and True

    cpp = compile_chunk(test_bool_expr)
    # 匹配完整赋值语句
    assert_code_contains(
        cpp,
        """
        void test_bool_expr() {
            mc::array<int> items = {};
            bool result = !items.empty() && true;
        }
        """,
    )


def test_int_conversion_from_float():
    """测试 int(float) 使用类型转换"""

    def test_int_float() -> None:
        x: float = 3.14
        y: int = int(x)

    cpp = compile_chunk(test_int_float)
    # 注意：这个测试验证 int(float) 不会调用 float.__int__（因为 float 没有此方法）
    # 而是使用 int 的构造函数
    assert_code_contains(
        cpp,
        """
        void test_int_float() {
            double x = 3.14;
            int y = static_cast<int>(x);
        }
        """,
    )


def test_str_conversion_from_int():
    """测试 str(int) 使用类型转换"""

    def test_str_int() -> None:
        x: int = 42
        s: str = str(x)

    cpp = compile_chunk(test_str_int)
    # 注意：这个测试验证 str(int) 使用 int.__str__ 方法
    assert_code_contains(
        cpp,
        """
        void test_str_int() {
            int x = 42;
            std::string s = mc::to_string(x);
        }
        """,
    )


def test_bool_conversion_not_applied_for_constructor():
    """测试 bool 构造函数（无参数）不受影响"""

    def test_bool_constructor() -> None:
        x: bool = bool()

    cpp = compile_chunk(test_bool_constructor)
    assert_code_contains(
        cpp,
        """
        void test_bool_constructor() {
            bool x = bool{};
        }
        """,
    )
